Codeforces Round 345 (Div. 2) D. Image Preview(二分搜索)

题意:

$n\le 5\times 10^5手机图片,每种图片可能是h的也可能是w的,w要观看的话就要有旋转花费b$
$观看一张图片需要1单位时间,手机图片显示是个环,滑动切换的花费是a$
$初始在第一张图片,切换到的图片必须要观看$
$给定T\le 10^9时间,问最多能看多少图片$

分析:

$特判第一张图片,预处理出前缀观看时间,和后缀观看时间$
$向右枚举一次,然后二分倒着能看多少,两者加起来,同理向左枚举,二分顺着能看多少$
$注意细节和边界$

代码:

//
//  Created by TaoSama on 2016-03-07
//  Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 5e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

int n, a, b, T;
int pre[N], suf[N];
char s[N];

int main() {
#ifdef LOCAL
    freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
//  freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    while(scanf("%d%d%d%d", &n, &a, &b, &T) == 4) {
        scanf("%s", s + 1);
        pre[1] = suf[n + 1] = 0;
        for(int i = 2; i <= n; ++i)
            pre[i] = pre[i - 1] + a + (s[i] == 'w' ? b : 0) + 1;
        for(int i = n; i; --i)
            suf[i] = suf[i + 1] + a + (s[i] == 'w' ? b : 0) + 1;
        reverse(suf + 1, suf + 1 + n);

        int first = (s[1] == 'w' ? b : 0) + 1;
        int ans = first <= T;
        for(int i = 2; i <= n; ++i) {
            if(pre[i] + first > T) break;
            int leave = T - pre[i] - first - (i - 1) * a;
            int can = upper_bound(suf + 1, suf + 1 + n, leave) - suf - 1;
            ans = max(ans, i + can);
        }
        for(int i = 1; i <= n; ++i) {
            if(suf[i] + first > T) break;
            int leave = T - suf[i] - first - i * a;
            int can = upper_bound(pre + 2, pre + 1 + n, leave) - pre - 2;
            ans = max(ans, i + can + 1);
        }
        ans = min(ans, n);
        printf("%d\n", ans);
    }
    return 0;
}